<?php

class rooter {

    private $_routes = array();
    private $_inspector;
    private $_request;
    private $_variables;
    private $_models = array(
        'indexModel',
        'kontaktModel',
        'omnieModel',
        'uslugiModel',
    );

    public function __construct() {
        
    }

    private function setInspector($name) 
    {
        $this->_inspector = new Inspector($name);
    }

    /*
     * pobranie routingu dla pojedynczej metody
     */
    public function getRoute($comment) {
         
        $comments = preg_split('/\n/',$comment);
        
        $newmatches = array();
        
        foreach($comments as $i=>$comment)
        {
            @preg_match('/(@route\s*[a-zA-Z0-9,\.\&-=()_\/\{()\}]*)/', $comment, $matches);
            
            if (!empty($matches[1])) 
            {
                $route = preg_split('/=/', $matches[1], 2, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
                
            } 
            elseif(!empty($matches[0]))
            {
                $route = preg_split('/=/', $matches[0], 2, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
            }
            
            if(@sizeof($route) != 0 )
            {   
                $newmatches[] = $route;
            }
        }
        
        if(!empty($newmatches[0]))
        {
            if($newmatches[1])
            {
                $match[] = trim($newmatches[1][1],'()');
            }
            $match[] = trim($newmatches[0][1], '()');
            return $match;
        }
        return null;
    }

    /**
     * testowa metoda do pobierania rougintów z tablicy
     */
    public function root_from_array($options)
    {
        $request = $this->getRequest();
        $request = implode('', $request);
     
        echo $request;
        
        $array = array(
            array(
                'pattern'=>'/',
                'class'=>'controllers\indexmodel',
                'method'=>'index',
                'cachetime'=>30
                ),
            array(
                'pattern'=>'/omnie',
                'class'=>'controllers\omniemodel',
                'method'=>'index'
                ),
            array(
                'pattern'=>'/kontakt',
                'class'=>'controllers\kontaktmodel',
                'method'=>'index'
                ),
            array(
                'pattern'=>'/uslugi',
                'class'=>'controllers\uslugimodel',
                'method'=>'index'
                ),
            array(
                'pattern'=>'/_SkyCMS',
                'class'=>'controllers\admin\tresci',
                'method'=>'index'
                )
            );
        
        foreach($array as $routes)
        {
            if($routes['pattern'] == $request)
            {   
                $cacheoptions = $options['caching'];
                $params = '';
                $class = $routes['class'];
                $method = $routes['method'];
                $view = new libs\view($cacheoptions);
                $model = new $class($options,true);
                $view->renderAdminTwig($class, $method, $model->$method($params),true);
                $znaleziony = true;
                break;
                
            }
        }
    }
    
    /**
     * pobiera routingi dla jednego modelu 
     */
    public function createRoutes() 
    {
        $inspector = $this->_inspector;
        $methods = $inspector->_getClassMethods();

        $newcomments = array();
        $additional = array();

        foreach ($methods as $i => $objects) 
        {
            $route = $this->getRoute($inspector->_getMethodMeta($objects->name));
           
            if (!empty($route)) 
            {
                $newcomments[$i] = array();
                $newcomments[$i]['class'] = $objects->class;
                $newcomments[$i]['method'] = $objects->name;
                $newcomments[$i]['route'] = $route[0];
                
                if(count($route)>1)
                {
                    $additional[$i] = array();
                    $additional[$i]['class'] = $objects->class;
                    $additional[$i]['method'] = $objects->name;
                    $additional[$i]['route'] = $route[1];
                }
                
                
            }
        }
        
        
        if(@is_array($additional[1]) && !in_array($additional[1],$newcomments))
        {
            $newcomments[] = $additional[1];
        }
        
        return array_values($newcomments);
    }

    /**
     * pobiera routingi dla wszystkich modeli
     */
    public function getAllRoutes($path) 
    {    
        foreach (new DirectoryIterator($path) as $file) 
        {
            $class = trim($file->getFilename(), '.php');
            $plik = pathinfo($file->getFilename());
            if (@$plik['extension'] == 'php' && $class != '_SkyCMSModel') 
            {
                $namespace = str_replace('/', '\\', $path);
                $model = $namespace . $class;
                $test = $this->setInspector($model);
                $routes[] = $this->createRoutes();
            }
        }

        $arrayRoutes = array();

        foreach ($routes as $i => $array) 
        {
            if (empty($array)) 
            {
                unset($routes[$i]);
            }
            foreach ($array as $single) 
            {
                $arrayRoutes[] = $single;
            }
        }
        
        return $arrayRoutes;
    }

    
    /*
     * porównujemy adres z nazwą skryptu i pozbywamy się części wspólnych, żeby
     * zostawić tylko faktyczne żądania (requesty) użytkownika
     */
    private function requestCleaner() 
    {
        $request = explode('/', $_SERVER['REQUEST_URI'], 4);

        $request = array_filter($request, function($item) {
                    return !empty($item);
                });

        foreach ($request as $i => $page) 
        {
            
            $page = str_replace('/', '\/', $page);
            $pattern = "/\/$page\//";

            if (preg_match($pattern, $_SERVER['SCRIPT_NAME'])) 
            {
                unset($request[$i]);
            }
        }

        return array_values($request);
    }

    
    /*
     * pobieramy już oczyszczonego requesta i dodajemy przedrostek "/"
     * żeby ewentualne żądania zgadzały się z podanymi przez nasz routingami
     */
    public function getRequest() 
    {
        $request = $this->requestCleaner();
        
        array_walk($request, function(&$item) {
                    $item = '/' . $item;
                });

        if (empty($request[0])) 
        {
            $request[0] = '/';
        }
        
        return $request;
    }

    public function dispatch($options) 
    {

        $request = $this->getRequest();
        $request = implode('', $request);
        
        if(strlen($request) > 1)
        {
            rtrim($request,'/');
        }
        
        $allRoutes = $this->getAllRoutes('controllers/');
        
        $znaleziony = false;
        
        if (preg_match('/\/_SkyCMS([a-zA-Z0-9,\.\&-=()_\/\{()\}]*).?/', $request, $matches)) 
        {
            $admin_root = array_slice($matches,1,1);
            $this->adminDispatch($admin_root,$options);
            $znaleziony = true;
        }
        
        foreach ($allRoutes as $route) 
        {
            if ($znaleziony) 
            {
                break;
            }
            
            $wyrazenie = preg_replace('/\{\w+\}/', '([\w\-]+).?', $route['route']);
            $wyrazenie = str_replace('/', '\/', $wyrazenie);
            $wyrazenie = str_replace('.','\.',$wyrazenie);
            
            if (preg_match('/^' . $wyrazenie . '$/', $request, $matches)) 
            {
                $cacheoptions = $options['caching'];
                $params = array_slice($matches,1,null,false);
                $class = $route['class'];
                $method = $route['method'];
                $view = new libs\view($cacheoptions);
                $model = new $class($options);
                $view->renderTwig($class, $method, $model->$method($params),true);
                $znaleziony = true;
                break;
            }
        }
        if ($znaleziony == false) 
        {
            include 'error.php';
        }
    }
    
    private function adminDispatch($admin_root,$options) 
    {
        $request = $admin_root[0];
        
        $request = rtrim($request,'/');
        
        if (empty($request)) 
        {
            $request = '/';
        }
        $znaleziony = false;
        $allRoutes = $this->getAllRoutes('controllers/admin/');

        foreach ($allRoutes as $route) 
        {
            if ($znaleziony) 
            {
                break;
            }
            
            $wyrazenie = preg_replace('/\{\w+\}/', '([\w\-=]+).?', $route['route']);

            $wyrazenie = str_replace('/', '\/', $wyrazenie);
            $wyrazenie = str_replace('.','\.',$wyrazenie);
            
            
            if (preg_match('/' . $wyrazenie . '$/', $request, $matches)) 
            {
                $params = array_slice($matches,1,null,false);  
                $class = $route['class'];
                $method = $route['method'];
                $view = new libs\view();
                $model = new $class($options,$request);
                $view->renderAdminTwig($class, $method, $model->$method($params));
                $znaleziony = true;
                break;
            }
        }
            
        if (!$znaleziony) 
        {
            $view = new libs\view();
            $model = new \controllers\admin\login($options,$request);
            $method = 'index';
            $view->renderAdminTwig($class, $method, $model->$method($params));
        }
    }

}
